using System;
using bitzhuwei.Compiler;

namespace bitzhuwei.AnsiCFormat {
    /// <summary>
    /// Correspond to the Vn node direct_declarator in the grammar(AnsiC).
    /// </summary>
    internal partial class Vndirect_declarator : IFullFormat {
        // [131] direct_declarator = 'identifier' ;
        // [132] direct_declarator = '(' declarator ')' ;
        // [133] direct_declarator = direct_declarator '[' constant_expression ']' ;
        // [134] direct_declarator = direct_declarator '[' ']' ;
        // [135] direct_declarator = direct_declarator '(' parameter_type_list ')' ;
        // [136] direct_declarator = direct_declarator '(' identifier_list ')' ;
        // [137] direct_declarator = direct_declarator '(' ')' ;


        private readonly IFullFormat complex;
        private readonly List<IFullFormat> postfix = new();

        private readonly TokenRange _scope;
        public TokenRange Scope => _scope;
        public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
            var config = new BlankConfig();
            context.PrintBlanksAnd(this.complex, preConfig, writer);
            var postfixCount = this.postfix.Count;
            for (var i = 0; i < postfixCount; i++) {
                if (i == 0) {
                    context.PrintCommentsBetween(this.postfix[i], this.complex, config, writer);
                }
                else {
                    context.PrintCommentsBetween(this.postfix[i], this.postfix[i - 1], config, writer);
                }
                context.PrintBlanksAnd(this.postfix[i], config, writer);
            }
        }

        // [133] direct_declarator = direct_declarator '[' constant_expression ']' ;
        public void Add(Token r2, Vnconstant_expression r1, Token r0) {
            this.postfix.Add(new Postfix0(r2, r1, r0));
            this._scope.end = r0.index;
        }
        class Postfix0 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                var config = new BlankConfig();
                context.PrintBlanksAnd(r2, preConfig, writer);
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(r0, config, writer);
            }
            public readonly Token r2;
            public readonly Vnconstant_expression r1;
            public readonly Token r0;
            public Postfix0(Token r2, Vnconstant_expression r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }
        }

        // [134] direct_declarator = direct_declarator '[' ']' ;
        public void Add(Token r1, Token r0) {
            this.postfix.Add(new Postfix1(r1, r0));
            this._scope.end = r0.index;
        }
        class Postfix1 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                var config = new BlankConfig();
                context.PrintBlanksAnd(r1, preConfig, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(r0, config, writer);
            }
            public readonly Token r1;
            public readonly Token r0;
            public Postfix1(Token r1, Token r0) {
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r1, r0);
            }
        }

        // [135] direct_declarator = direct_declarator '(' parameter_type_list ')' ;
        public void Add(Token r2, Vnparameter_type_list r1, Token r0) {
            this.postfix.Add(new Postfix2(r2, r1, r0));
            this._scope.end = r0.index;
        }
        class Postfix2 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                var config = new BlankConfig();
                context.PrintBlanksAnd(r2, preConfig, writer);
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(r0, config, writer);
            }
            public readonly Token r2;
            public readonly Vnparameter_type_list r1;
            public readonly Token r0;
            public Postfix2(Token r2, Vnparameter_type_list r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }
        }

        // [136] direct_declarator = direct_declarator '(' identifier_list ')' ;
        public void Add(Token r2, Vnidentifier_list r1, Token r0) {
            this.postfix.Add(new Postfix3(r2, r1, r0));
            this._scope.end = r0.index;
        }
        class Postfix3 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                var config = new BlankConfig();
                context.PrintBlanksAnd(r2, preConfig, writer);
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(r0, config, writer);
            }
            public readonly Token r2;
            public readonly Vnidentifier_list r1;
            public readonly Token r0;
            public Postfix3(Token r2, Vnidentifier_list r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }
        }

        // [137] direct_declarator = direct_declarator '(' ')' ;
        // Pre/Postfix4 repeated with Pre/Postfix1


        // [131] direct_declarator = 'identifier' ;
        public Vndirect_declarator(Token r0) {
            this.complex = new complex0(r0);
            this._scope = new TokenRange(r0);
        }
        class complex0 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(r0, preConfig, writer);
            }
            public readonly Token r0;
            public complex0(Token r0) {
                this.r0 = r0;
                this._scope = new TokenRange(r0);
            }
        }

        // [132] direct_declarator = '(' declarator ')' ;
        public Vndirect_declarator(Token r2, Vndeclarator r1, Token r0) {
            this.complex = new complex1(r2, r1, r0);
            this._scope = new TokenRange(r2, r0);
        }
        class complex1 : IFullFormat {
            private readonly TokenRange _scope;
            public TokenRange Scope => _scope;
            public void FullFormat(BlankConfig? preConfig, TextWriter writer, FormatContext context) {
                var config = new BlankConfig();
                context.PrintBlanksAnd(r2, preConfig, writer);
                context.PrintCommentsBetween(r2, r1, config, writer);
                context.PrintBlanksAnd(r1, config, writer);
                context.PrintCommentsBetween(r1, r0, config, writer);
                context.PrintBlanksAnd(r0, config, writer);
            }
            public readonly Token r2;
            public readonly Vndeclarator r1;
            public readonly Token r0;
            public complex1(Token r2, Vndeclarator r1, Token r0) {
                this.r2 = r2;
                this.r1 = r1;
                this.r0 = r0;
                this._scope = new TokenRange(r2, r0);
            }
        }



    }
}
